package com.hrc.springboot.service;

import com.hrc.springboot.bean.Employee;
import com.hrc.springboot.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;

@CacheConfig(cacheNames = "emp", cacheManager = "cacheManager")
@Service
public class EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 方法运行的结果进行缓存，以后再运行相同的数据，直接从缓存中获取，不调用方法
     * <p>
     * CacheManager管理多个Cache组件的，对缓存的真正CRUD操作都在Cache组件中
     * 每一个缓存的名字具有唯一性
     * 属性，
     * cacheNames/value：指定缓存的名字，
     * key：缓存数据时使用的key，用它来指定，不指定默认使用方法参数的值  key：1-value：方法的返回值
     * 可以使用SpEL表达式来指定缓存名字；#id，参数id的值
     * keyGenerator：key生成器，可以自己指定Key的生成器的组件id
     * key/keyGenerator两种属性二选一
     * cacheManager：指定缓存管理器，或者使用cacheResolver指定缓存解析器，二者作用相同，因此这两种属性也是二选一
     * Condition：指定符合条件的情况下可以缓存
     * unless：此属性指定的条件为true，即为不缓存，可以获取到结果进行判断
     * sync：是否使用异步模式
     * 缓存工作原理
     * 1、自动配置类：CacheAutoConfiguration
     * 2、缓存配置类：
     * 3、默认生效的配置类：SimpleCacheConfiguration
     * 4、给容器中注册了一个CacheManager，ConcurrentMapCacheManager
     * 5、可以获取和创建ConcurrentMapCacheManager类型的缓存组件，作用是将数据保存在ConcurrentMap中
     * 运行流程
     * 1、方法运行之前，先去查询cache组件，按照指定的缓存名称获取
     * CacheManager先获取相应的缓存，第一次获取缓存如果没有就会自动创建
     * 2、在Cache中查找缓存内容，使用key，默认方法的参数
     *
     * @param id
     * @return
     */
    @Cacheable(cacheNames = "emp"/*, keyGenerator = "myKeyGenerator", condition = "#a0>1", unless = "#a0 == 2"*/)
    public Employee getEmpById(Integer id) {
        System.out.printf("查询%s号\n", id);
        return employeeMapper.getEmpById(id);
    }

    // 在@Cacheable中，“#result”不能使用
    @CachePut(value = "emp", key = "#result.id")
    public Employee updateEmp(Employee employee) {
        System.out.printf("正在修改%s号数据\n", employee.getId());
        employeeMapper.updateEmp(employee);
        return employee;
    }

    // allEntries = true,清除缓存中的全部数据
    // beforeInvocation = false,代表在方法执行之后清除缓存，
    // 如果等于true代表清除缓存操作是在方法运行之前执行，
    @CacheEvict(value = "emp", key = "#id")
    public void deleteEmp(Integer id) {
        System.out.println("deleteEmp:" + id);
    }

    @Caching(
            cacheable = {
                    @Cacheable(/*value = "emp",*/ key = "#lastName")
            },
            put = {
                    @CachePut(/*value = "emp",*/ key = "#result.id"),
                    @CachePut(value = "emp", key = "#result.email")
            }
    )
    public Employee getEmpByLastName(String lastName) {
        return employeeMapper.getEmpByLastName(lastName);
    }

}
